# -*- coding: utf-8 -*-
"""
报表渲染器 - 负责将数据渲染为不同格式的报表文件
"""
from abc import ABC, abstractmethod
from typing import Dict, Any
from datetime import datetime
from jinja2 import Template
import io

from app.blueprints.reports.registry.registry import TemplateRegistry


class BaseRenderer(ABC):
    """渲染器基类"""
    
    @abstractmethod
    def render(self, data: Dict[str, Any]) -> bytes:
        """
        渲染数据为文件内容
        :param data: 数据字典
        :return: 文件内容（字节）
        """
        pass
    
    @abstractmethod
    def get_file_type(self) -> str:
        """
        获取文件类型
        :return: 文件类型（html/excel/csv/pdf）
        """
        pass


class HtmlRenderer(BaseRenderer):
    """HTML渲染器"""
    
    def __init__(self, template_code: str, title: str = None, time_start: str = None, time_end: str = None):
        """
        初始化HTML渲染器
        :param template_code: 模板编码，用于选择HTML模板
        :param title: 报表标题（可选）
        :param time_start: 统计开始时间（可选）
        :param time_end: 统计结束时间（可选）
        """
        self.template_code = template_code
        self.title = title
        self.time_start = time_start
        self.time_end = time_end
    
    def render(self, data: Dict[str, Any]) -> bytes:
        """
        渲染HTML
        :param data: 数据字典
        :return: HTML内容（字节）
        """
        # 获取对应模板
        template_html = self._get_template()
        
        # 如果没有设置标题，使用模板名称作为默认值
        descriptor = TemplateRegistry.get(self.template_code)

        report_title = self.title
        if not report_title:
            if descriptor:
                report_title = descriptor.name
            elif self.template_code == 'data_quality_monitor':
                report_title = '数据质量监控报表'
            elif self.template_code == 'cps_data_quality_monitor':
                report_title = 'CPS基础数据同步专用报表'
            elif self.template_code == 'cps_base_statistics_report':
                report_title = 'CPS基础表统计报表'
            else:
                report_title = '数据报表'
        
        # 对于使用 query_result 格式的模板，确保数据格式正确
        query_result_templates = [
            'cps_data_quality_monitor',
            'cps_base_statistics_report',
            'starrocks_cluster_comparison_report',
            'kafka_topic_no_update_report',
            'starrocks_table_growth_report'
        ]
        if self.template_code in query_result_templates and 'query_result' in data:
            query_result = data.get('query_result', {})
            columns = query_result.get('columns', [])
            rows = query_result.get('rows', [])
            
            # 确保 rows 是列表的列表，而不是其他格式
            processed_rows = []
            for row in rows:
                if isinstance(row, (list, tuple)):
                    processed_rows.append(list(row))
                elif isinstance(row, dict):
                    # 如果是字典，转换为列表（按列顺序）
                    processed_rows.append([row.get(col, '') for col in columns])
                else:
                    # 其他类型，尝试转换为列表
                    processed_rows.append([str(row)] if row else [])
            
            data = {
                'query_result': {
                    'columns': columns,
                    'rows': processed_rows
                }
            }
        
        # 准备渲染上下文
        context = {
            'data': data,
            'generated_at': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            'template_code': self.template_code,
            'title': report_title,
            'time_start': self.time_start,
            'time_end': self.time_end,
            'display_fields': descriptor.display_fields if descriptor else None,
            'template_meta': descriptor,
        }
        
        # 渲染
        template = Template(template_html)
        html = template.render(**context)
        
        return html.encode('utf-8')
    
    def get_file_type(self) -> str:
        return 'html'
    
    def _get_template(self) -> str:
        """获取HTML模板"""
        if self.template_code == 'data_quality_monitor':
            return self._data_quality_monitor_template()
        elif self.template_code == 'cps_data_quality_monitor':
            return self._cps_data_quality_monitor_template()
        elif self.template_code == 'cps_base_statistics_report':
            return self._cps_data_quality_monitor_template()  # 使用相同的模板（都使用query_result格式）
        elif self.template_code == 'generic_data_quality_monitor':
            return self._generic_data_quality_monitor_template()
        # 已清理所有模板特定实现，使用默认模板
        # 后续将逐个实现新模板
        return self._default_template()
    
    def _data_quality_monitor_template(self) -> str:
        """数据质量监控报表HTML模板"""
        return """
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{ title }}</title>
    <style>
        body { font-family: Arial, "Microsoft YaHei", sans-serif; margin: 20px; background: #f5f5f5; }
        .container { max-width: 1200px; margin: 0 auto; background: white; padding: 30px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
        h1 { color: #333; border-bottom: 3px solid #409EFF; padding-bottom: 10px; }
        h2 { color: #555; margin-top: 30px; }
        .meta { color: #999; font-size: 14px; margin-bottom: 20px; }
        .meta-label { font-weight: 600; color: #666; }
        table { width: 100%; border-collapse: collapse; margin: 20px 0; }
        th, td { border: 1px solid #ddd; padding: 12px; text-align: left; }
        th { background-color: #409EFF; color: white; }
        tr:nth-child(even) { background-color: #f9f9f9; }
        .status-normal { color: #67C23A; font-weight: bold; }
        .status-warning { color: #E6A23C; font-weight: bold; }
        .status-error { color: #F56C6C; font-weight: bold; }
        .no-data { text-align: center; color: #999; padding: 20px; }
        .time-range { background: #f0f7ff; padding: 8px 12px; border-left: 4px solid #409EFF; margin: 10px 0; border-radius: 4px; }
    </style>
</head>
<body>
    <div class="container">
        <h1>{{ title }}</h1>
        <div class="meta">
            <div><span class="meta-label">生成时间：</span>{{ generated_at }}</div>
            <div><span class="meta-label">模板编码：</span>{{ template_code }}</div>
            {% if time_start and time_end %}
            <div class="time-range">
                <span class="meta-label">统计时间范围：</span>{{ time_start }} 至 {{ time_end }}
            </div>
            {% elif time_start or time_end %}
            <div class="time-range">
                <span class="meta-label">统计时间：</span>{% if time_start %}{{ time_start }}{% endif %}{% if time_start and time_end %} 至 {% endif %}{% if time_end %}{{ time_end }}{% endif %}
            </div>
            {% else %}
            <div class="meta"><span class="meta-label">统计时间范围：</span>全部数据</div>
            {% endif %}
        </div>
        
        {% if data and data.data and data.data|length > 0 %}
        <h2>监控结果</h2>
        <table>
            <thead>
                <tr>
                    {% if 'platform' in data.data[0] %}<th>平台</th>{% endif %}
                    {% if 'platform_summary' in data.data[0] %}<th>平台汇总</th>{% endif %}
                    {% if 'source_layer' in data.data[0] %}<th>原始层(源表)</th>{% endif %}
                    {% if 'source_total_count' in data.data[0] %}<th>原始层商品总数</th>{% endif %}
                    {% if 'dws_total_count' in data.data[0] %}<th>目标表商品总数</th>{% endif %}
                    {% if 'dws_on_sale_count' in data.data[0] %}<th>目标表上架商品数</th>{% endif %}
                    {% if 'dws_off_sale_count' in data.data[0] %}<th>目标表下架商品数</th>{% endif %}
                    {% if 'sync_rate' in data.data[0] %}<th>同步率</th>{% endif %}
                    {% if 'data_status' in data.data[0] %}<th>数据状态</th>{% endif %}
                </tr>
            </thead>
            <tbody>
                {% for row in data.data %}
                <tr>
                    {% if 'platform' in row %}<td>{{ row.platform }}</td>{% endif %}
                    {% if 'platform_summary' in row %}<td>{{ row.platform_summary }}</td>{% endif %}
                    {% if 'source_layer' in row %}<td>{{ row.source_layer }}</td>{% endif %}
                    {% if 'source_total_count' in row %}<td>{{ row.source_total_count }}</td>{% endif %}
                    {% if 'dws_total_count' in row %}<td>{{ row.dws_total_count }}</td>{% endif %}
                    {% if 'dws_on_sale_count' in row %}<td>{{ row.dws_on_sale_count }}</td>{% endif %}
                    {% if 'dws_off_sale_count' in row %}<td>{{ row.dws_off_sale_count }}</td>{% endif %}
                    {% if 'sync_rate' in row %}<td>{{ row.sync_rate }}</td>{% endif %}
                    {% if 'data_status' in row %}
                    <td>
                        {% if row.data_status == '正常' %}
                        <span class="status-normal">{{ row.data_status }}</span>
                        {% elif row.data_status == '同步率过低' %}
                        <span class="status-warning">{{ row.data_status }}</span>
                        {% else %}
                        <span class="status-error">{{ row.data_status }}</span>
                        {% endif %}
                    </td>
                    {% endif %}
                </tr>
                {% endfor %}
            </tbody>
        </table>
        
        {% if data.summary %}
        <h2>汇总信息</h2>
        <div style="background: #f9f9f9; padding: 15px; border-radius: 5px;">
            <p><strong>原始层总数：</strong>{{ data.summary.source_total_count }}</p>
            <p><strong>DWS总数：</strong>{{ data.summary.dws_total_count }}</p>
            <p><strong>同步率：</strong>{{ data.summary.sync_rate }}</p>
            <p><strong>数据状态：</strong>
                {% if data.summary.data_status == '正常' %}
                <span class="status-normal">{{ data.summary.data_status }}</span>
                {% elif data.summary.data_status == '同步率过低' %}
                <span class="status-warning">{{ data.summary.data_status }}</span>
                {% else %}
                <span class="status-error">{{ data.summary.data_status }}</span>
                {% endif %}
            </p>
        </div>
        {% endif %}
        {% else %}
        <div class="no-data">暂无数据</div>
        {% endif %}
    </div>
</body>
</html>
        """
    
    def _default_template(self) -> str:
        """默认HTML模板"""
        return """
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{ title }}</title>
    <style>
        body { font-family: Arial, "Microsoft YaHei", sans-serif; margin: 20px; background: #f5f5f5; }
        .container { max-width: 1200px; margin: 0 auto; background: white; padding: 30px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
        h1 { color: #333; border-bottom: 3px solid #409EFF; padding-bottom: 10px; }
        h2 { color: #555; margin-top: 30px; }
        .meta { color: #999; font-size: 14px; margin-bottom: 20px; }
        .meta-label { font-weight: 600; color: #666; }
        table { width: 100%; border-collapse: collapse; margin: 20px 0; }
        th, td { border: 1px solid #ddd; padding: 12px; text-align: left; }
        th { background-color: #409EFF; color: white; }
        tr:nth-child(even) { background-color: #f9f9f9; }
        .no-data { text-align: center; color: #999; padding: 20px; }
        .time-range { background: #f0f7ff; padding: 8px 12px; border-left: 4px solid #409EFF; margin: 10px 0; border-radius: 4px; }
    </style>
</head>
<body>
    <div class="container">
        <h1>{{ title }}</h1>
        <div class="meta">
            <div><span class="meta-label">生成时间：</span>{{ generated_at }}</div>
            <div><span class="meta-label">模板编码：</span>{{ template_code }}</div>
            {% if time_start and time_end %}
            <div class="time-range">
                <span class="meta-label">统计时间范围：</span>{{ time_start }} 至 {{ time_end }}
            </div>
            {% elif time_start or time_end %}
            <div class="time-range">
                <span class="meta-label">统计时间：</span>{% if time_start %}{{ time_start }}{% endif %}{% if time_start and time_end %} 至 {% endif %}{% if time_end %}{{ time_end }}{% endif %}
            </div>
            {% else %}
            <div class="meta"><span class="meta-label">统计时间范围：</span>全部数据</div>
            {% endif %}
        </div>
        
        <h2>报表数据</h2>
        <pre>{{ data }}</pre>
    </div>
</body>
</html>
        """
    
    def _generic_data_quality_monitor_template(self) -> str:
        """通用数据同步质量报表HTML模板"""
        return """
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{ title }}</title>
    <style>
        body { font-family: Arial, "Microsoft YaHei", sans-serif; margin: 20px; background: #f5f5f5; }
        .container { max-width: 1200px; margin: 0 auto; background: white; padding: 30px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
        h1 { color: #333; border-bottom: 3px solid #409EFF; padding-bottom: 10px; }
        h2 { color: #555; margin-top: 30px; }
        .meta { color: #999; font-size: 14px; margin-bottom: 20px; }
        .meta-label { font-weight: 600; color: #666; }
        table { width: 100%; border-collapse: collapse; margin: 20px 0; }
        th, td { border: 1px solid #ddd; padding: 12px; text-align: left; }
        th { background-color: #409EFF; color: white; }
        tr:nth-child(even) { background-color: #f9f9f9; }
        .status-normal { color: #67C23A; font-weight: bold; }
        .status-warning { color: #E6A23C; font-weight: bold; }
        .status-error { color: #F56C6C; font-weight: bold; }
        .no-data { text-align: center; color: #999; padding: 20px; }
        .time-range { background: #f0f7ff; padding: 8px 12px; border-left: 4px solid #409EFF; margin: 10px 0; border-radius: 4px; }
    </style>
</head>
<body>
    <div class="container">
        <h1>{{ title }}</h1>
        <div class="meta">
            <div><span class="meta-label">生成时间：</span>{{ generated_at }}</div>
            <div><span class="meta-label">模板编码：</span>{{ template_code }}</div>
            {% if time_start and time_end %}
            <div class="time-range">
                <span class="meta-label">统计时间范围：</span>{{ time_start }} 至 {{ time_end }}
            </div>
            {% elif time_start or time_end %}
            <div class="time-range">
                <span class="meta-label">统计时间：</span>{% if time_start %}{{ time_start }}{% endif %}{% if time_start and time_end %} 至 {% endif %}{% if time_end %}{{ time_end }}{% endif %}
            </div>
            {% else %}
            <div class="meta"><span class="meta-label">统计时间范围：</span>全部数据</div>
            {% endif %}
        </div>
        
        {% if data and data.data and data.data|length > 0 %}
        <h2>监控结果</h2>
        <table>
            <thead>
                <tr>
                    {% if 'source_table' in data.data[0] %}<th>源表</th>{% endif %}
                    {% if 'target_table' in data.data[0] %}<th>目标表</th>{% endif %}
                    {% if 'source_total_count' in data.data[0] %}<th>源表总数</th>{% endif %}
                    {% if 'target_total_count' in data.data[0] %}<th>目标表总数</th>{% endif %}
                    {% if 'sync_rate' in data.data[0] %}<th>同步率</th>{% endif %}
                    {% if 'data_status' in data.data[0] %}<th>数据状态</th>{% endif %}
                    {% for key in data.data[0] %}
                        {% if key not in ['source_table', 'target_table', 'source_total_count', 'target_total_count', 'sync_rate', 'data_status'] %}
                        <th>{{ key }}</th>
                        {% endif %}
                    {% endfor %}
                </tr>
            </thead>
            <tbody>
                {% for row in data.data %}
                <tr>
                    {% if 'source_table' in row %}<td>{{ row.source_table }}</td>{% endif %}
                    {% if 'target_table' in row %}<td>{{ row.target_table }}</td>{% endif %}
                    {% if 'source_total_count' in row %}<td>{{ row.source_total_count }}</td>{% endif %}
                    {% if 'target_total_count' in row %}<td>{{ row.target_total_count }}</td>{% endif %}
                    {% if 'sync_rate' in row %}<td>{{ row.sync_rate }}</td>{% endif %}
                    {% if 'data_status' in row %}
                    <td>
                        {% if row.data_status == '正常' %}
                        <span class="status-normal">{{ row.data_status }}</span>
                        {% elif row.data_status == '同步率过低' %}
                        <span class="status-warning">{{ row.data_status }}</span>
                        {% else %}
                        <span class="status-error">{{ row.data_status }}</span>
                        {% endif %}
                    </td>
                    {% endif %}
                    {% for key, value in row.items() %}
                        {% if key not in ['source_table', 'target_table', 'source_total_count', 'target_total_count', 'sync_rate', 'data_status'] %}
                        <td>{{ value }}</td>
                        {% endif %}
                    {% endfor %}
                </tr>
                {% endfor %}
            </tbody>
        </table>
        {% else %}
        <div class="no-data">暂无数据</div>
        {% endif %}
    </div>
</body>
</html>
        """
    
    def _cps_data_quality_monitor_template(self) -> str:
        """CPS基础数据同步专用报表HTML模板（处理query_result格式）"""
        return """
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{ title }}</title>
    <style>
        body { font-family: Arial, "Microsoft YaHei", sans-serif; margin: 20px; background: #f5f5f5; }
        .container { max-width: 1200px; margin: 0 auto; background: white; padding: 30px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
        h1 { color: #333; border-bottom: 3px solid #409EFF; padding-bottom: 10px; }
        h2 { color: #555; margin-top: 30px; }
        .meta { color: #999; font-size: 14px; margin-bottom: 20px; }
        .meta-label { font-weight: 600; color: #666; }
        table { width: 100%; border-collapse: collapse; margin: 20px 0; }
        th, td { border: 1px solid #ddd; padding: 12px; text-align: left; }
        th { background-color: #409EFF; color: white; }
        tr:nth-child(even) { background-color: #f9f9f9; }
        .status-normal { color: #67C23A; font-weight: bold; }
        .status-warning { color: #E6A23C; font-weight: bold; }
        .status-error { color: #F56C6C; font-weight: bold; }
        .no-data { text-align: center; color: #999; padding: 20px; }
        .time-range { background: #f0f7ff; padding: 8px 12px; border-left: 4px solid #409EFF; margin: 10px 0; border-radius: 4px; }
    </style>
</head>
<body>
    <div class="container">
        <h1>{{ title }}</h1>
        <div class="meta">
            <div><span class="meta-label">生成时间：</span>{{ generated_at }}</div>
            <div><span class="meta-label">模板编码：</span>{{ template_code }}</div>
            {% if time_start and time_end %}
            <div class="time-range">
                <span class="meta-label">统计时间范围：</span>{{ time_start }} 至 {{ time_end }}
            </div>
            {% elif time_start or time_end %}
            <div class="time-range">
                <span class="meta-label">统计时间：</span>{% if time_start %}{{ time_start }}{% endif %}{% if time_start and time_end %} 至 {% endif %}{% if time_end %}{{ time_end }}{% endif %}
            </div>
            {% else %}
            <div class="meta"><span class="meta-label">统计时间范围：</span>全部数据</div>
            {% endif %}
        </div>
        
        {% if data and data.query_result and data.query_result.rows and data.query_result.rows|length > 0 %}
        <h2>监控结果</h2>
        <table>
            <thead>
                <tr>
                    {% for col in data.query_result.columns %}
                    <th>{{ col }}</th>
                    {% endfor %}
                </tr>
            </thead>
            <tbody>
                {% for row in data.query_result.rows %}
                <tr>
                    {% for col_idx in range(data.query_result.columns|length) %}
                    <td>
                        {% set col_name = data.query_result.columns[col_idx] %}
                        {% set cell_value = row[col_idx] if col_idx < row|length else '' %}
                        {% if col_name == '数据状态' and cell_value in ['正常', '同步率过低', '未同步', '无原始数据'] %}
                            {% if cell_value == '正常' %}
                            <span class="status-normal">{{ cell_value }}</span>
                            {% elif cell_value == '同步率过低' %}
                            <span class="status-warning">{{ cell_value }}</span>
                            {% else %}
                            <span class="status-error">{{ cell_value }}</span>
                            {% endif %}
                        {% else %}
                            {{ cell_value if cell_value is not none else '' }}
                        {% endif %}
                    </td>
                    {% endfor %}
                </tr>
                {% endfor %}
            </tbody>
        </table>
        {% else %}
        <div class="no-data">暂无数据</div>
        {% endif %}
    </div>
</body>
</html>
        """
    


class ExcelRenderer(BaseRenderer):
    """Excel渲染器"""
    
    def __init__(self, template_code: str, title: str = None, time_start: str = None, time_end: str = None):
        """
        初始化Excel渲染器
        :param template_code: 模板编码
        :param title: 报表标题（可选）
        :param time_start: 统计开始时间（可选）
        :param time_end: 统计结束时间（可选）
        """
        self.template_code = template_code
        self.title = title
        self.time_start = time_start
        self.time_end = time_end
    
    def render(self, data: Dict[str, Any]) -> bytes:
        """渲染Excel"""
        try:
            from openpyxl import Workbook
            from openpyxl.styles import Font, PatternFill, Alignment
        except ImportError:
            raise ImportError("需要安装 openpyxl 库：pip install openpyxl")
        
        descriptor = TemplateRegistry.get(self.template_code)
        
        # 对于使用 query_result 格式的模板，确保数据格式正确
        query_result_templates = [
            'cps_data_quality_monitor',
            'cps_base_statistics_report',
            'starrocks_cluster_comparison_report',
            'kafka_topic_no_update_report',
            'starrocks_table_growth_report'
        ]
        if self.template_code in query_result_templates and 'query_result' in data:
            query_result = data.get('query_result', {})
            columns = query_result.get('columns', [])
            rows = query_result.get('rows', [])
            
            # 确保 rows 是列表的列表，而不是其他格式
            processed_rows = []
            for row in rows:
                if isinstance(row, (list, tuple)):
                    processed_rows.append(list(row))
                elif isinstance(row, dict):
                    # 如果是字典，转换为列表（按列顺序）
                    processed_rows.append([row.get(col, '') for col in columns])
                else:
                    # 其他类型，尝试转换为列表
                    processed_rows.append([str(row)] if row else [])
            
            data = {
                'query_result': {
                    'columns': columns,
                    'rows': processed_rows
                }
            }
        
        wb = Workbook()
        
        # 根据模板编码选择渲染方式
        if self.template_code == 'data_quality_monitor':
            self._render_data_quality_monitor(wb, data)
        elif self.template_code == 'cps_data_quality_monitor':
            self._render_cps_data_quality_monitor(wb, data)
        elif self.template_code == 'cps_base_statistics_report':
            self._render_cps_data_quality_monitor(wb, data)  # 使用相同的渲染逻辑（都使用query_result格式）
        elif self.template_code == 'generic_data_quality_monitor':
            self._render_generic_data_quality_monitor(wb, data)
        else:
            # 已清理所有模板特定实现，使用默认渲染
            # 后续将逐个实现新模板
            self._render_default(wb, data)
        
        # 将工作簿写入内存并返回字节内容
        buf = io.BytesIO()
        wb.save(buf)
        buf.seek(0)
        return buf.getvalue()
    
    def _render_data_quality_monitor(self, wb, data):
        """渲染数据质量监控报表到Excel"""
        from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
        
        ws = wb.active
        ws.title = "数据质量监控"
        
        # 标题样式
        title_font = Font(name='微软雅黑', size=16, bold=True)
        header_fill = PatternFill(start_color='409EFF', end_color='409EFF', fill_type='solid')
        header_font = Font(name='微软雅黑', size=11, bold=True, color='FFFFFF')
        normal_font = Font(name='微软雅黑', size=10)
        border = Border(
            left=Side(style='thin'),
            right=Side(style='thin'),
            top=Side(style='thin'),
            bottom=Side(style='thin')
        )
        
        descriptor = TemplateRegistry.get(self.template_code)
        report_title = self.title or (descriptor.name if descriptor else '数据质量监控报表')
        
        # 写入标题
        ws['A1'] = report_title
        ws['A1'].font = title_font
        # 先确定表头数量，以便正确合并单元格
        headers = []
        if data.get('data') and len(data['data']) > 0:
            row = data['data'][0]
            if 'platform' in row:
                headers.append('平台')
            if 'platform_summary' in row:
                headers.append('平台汇总')
            if 'source_layer' in row:
                headers.append('原始层(源表)')
            if 'source_total_count' in row:
                headers.append('原始层商品总数')
            if 'dws_total_count' in row:
                headers.append('目标表商品总数')
            if 'dws_on_sale_count' in row:
                headers.append('目标表上架商品数')
            if 'dws_off_sale_count' in row:
                headers.append('目标表下架商品数')
            if 'sync_rate' in row:
                headers.append('同步率')
            if 'data_status' in row:
                headers.append('数据状态')
        
        # 确定合并单元格的列范围（如果没有headers，使用 I 列作为默认值）
        last_col = chr(64 + len(headers)) if headers else 'I'
        
        ws.merge_cells(f'A1:{last_col}1')
        
        # 写入生成时间
        row_num = 2
        ws[f'A{row_num}'] = f"生成时间：{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
        ws[f'A{row_num}'].font = normal_font
        ws.merge_cells(f'A{row_num}:{last_col}{row_num}')
        
        # 写入统计时间范围
        row_num += 1
        if self.time_start and self.time_end:
            ws[f'A{row_num}'] = f"统计时间范围：{self.time_start} 至 {self.time_end}"
        elif self.time_start or self.time_end:
            time_range_str = f"统计时间：{self.time_start or ''} 至 {self.time_end or ''}"
            ws[f'A{row_num}'] = time_range_str
        else:
            ws[f'A{row_num}'] = "统计时间范围：全部数据"
        ws[f'A{row_num}'].font = normal_font
        ws.merge_cells(f'A{row_num}:{last_col}{row_num}')
        
        # 表头从下一行开始
        header_row = row_num + 1
        
        if headers:
            for col_idx, header in enumerate(headers, start=1):
                cell = ws.cell(row=header_row, column=col_idx, value=header)
                cell.font = header_font
                cell.fill = header_fill
                cell.alignment = Alignment(horizontal='center', vertical='center')
                cell.border = border
            
            # 写入数据（从表头下一行开始）
            data_start_row = header_row + 1
            for row_idx, row_data in enumerate(data.get('data', []), start=data_start_row):
                col_idx = 1
                for header in headers:
                    key = header
                    if header == '平台':
                        key = 'platform'
                    elif header == '平台汇总':
                        key = 'platform_summary'
                    elif header == '原始层(源表)':
                        key = 'source_layer'
                    elif header == '原始层商品总数':
                        key = 'source_total_count'
                    elif header == '目标表商品总数':
                        key = 'dws_total_count'
                    elif header == '目标表上架商品数':
                        key = 'dws_on_sale_count'
                    elif header == '目标表下架商品数':
                        key = 'dws_off_sale_count'
                    elif header == '同步率':
                        key = 'sync_rate'
                    elif header == '数据状态':
                        key = 'data_status'
                    
                    cell = ws.cell(row=row_idx, column=col_idx, value=row_data.get(key, ''))
                    cell.font = normal_font
                    cell.border = border
                    col_idx += 1
            
            # 调整列宽
            for col_idx in range(1, len(headers) + 1):
                col_letter = chr(64 + col_idx)
                ws.column_dimensions[col_letter].width = 20
            
            # 计算汇总信息的起始行（在数据行之后）
            if data.get('summary'):
                summary_row = data_start_row + len(data.get('data', [])) + 1
            else:
                summary_row = None
        else:
            # 如果没有数据，汇总信息直接放在时间范围下面
            data_start_row = header_row
            if data.get('summary'):
                summary_row = data_start_row + 1
            else:
                summary_row = None
        
        # 写入汇总信息
        if data.get('summary') and summary_row:
            ws.cell(row=summary_row, column=1, value='汇总信息').font = Font(name='微软雅黑', size=12, bold=True)
            summary_row += 1
            ws.cell(row=summary_row, column=1, value='原始层总数：').font = normal_font
            ws.cell(row=summary_row, column=2, value=data['summary'].get('source_total_count', 0)).font = normal_font
            summary_row += 1
            ws.cell(row=summary_row, column=1, value='DWS总数：').font = normal_font
            ws.cell(row=summary_row, column=2, value=data['summary'].get('dws_total_count', 0)).font = normal_font
            summary_row += 1
            ws.cell(row=summary_row, column=1, value='同步率：').font = normal_font
            ws.cell(row=summary_row, column=2, value=data['summary'].get('sync_rate', '0%')).font = normal_font
            summary_row += 1
            ws.cell(row=summary_row, column=1, value='数据状态：').font = normal_font
            ws.cell(row=summary_row, column=2, value=data['summary'].get('data_status', '未知')).font = normal_font
    
    def _render_cps_data_quality_monitor(self, wb, data):
        """渲染CPS基础数据同步专用报表到Excel（处理query_result格式）"""
        from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
        
        ws = wb.active
        ws.title = "CPS数据质量监控"
        
        # 标题样式
        title_font = Font(name='微软雅黑', size=16, bold=True)
        header_fill = PatternFill(start_color='409EFF', end_color='409EFF', fill_type='solid')
        header_font = Font(name='微软雅黑', size=11, bold=True, color='FFFFFF')
        normal_font = Font(name='微软雅黑', size=10)
        border = Border(
            left=Side(style='thin'),
            right=Side(style='thin'),
            top=Side(style='thin'),
            bottom=Side(style='thin')
        )
        
        descriptor = TemplateRegistry.get(self.template_code)
        report_title = self.title or (descriptor.name if descriptor else 'CPS基础数据同步专用报表')
        
        # 获取查询结果
        query_result = data.get('query_result', {})
        columns = query_result.get('columns', [])
        rows = query_result.get('rows', [])
        
        if not columns or not rows:
            ws['A1'] = report_title
            ws['A1'].font = title_font
            ws['A2'] = '暂无数据'
            ws['A2'].font = normal_font
            return
        
        # 写入标题
        ws['A1'] = report_title
        ws['A1'].font = title_font
        last_col = chr(64 + len(columns)) if len(columns) <= 26 else 'Z'
        ws.merge_cells(f'A1:{last_col}1')
        
        # 写入生成时间
        row_num = 2
        ws[f'A{row_num}'] = f"生成时间：{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
        ws[f'A{row_num}'].font = normal_font
        ws.merge_cells(f'A{row_num}:{last_col}{row_num}')
        
        # 写入统计时间范围
        row_num += 1
        if self.time_start and self.time_end:
            ws[f'A{row_num}'] = f"统计时间范围：{self.time_start} 至 {self.time_end}"
        elif self.time_start or self.time_end:
            time_range_str = f"统计时间：{self.time_start or ''} 至 {self.time_end or ''}"
            ws[f'A{row_num}'] = time_range_str
        else:
            ws[f'A{row_num}'] = "统计时间范围：全部数据"
        ws[f'A{row_num}'].font = normal_font
        ws.merge_cells(f'A{row_num}:{last_col}{row_num}')
        
        # 表头从下一行开始
        header_row = row_num + 1
        
        # 写入表头
        for col_idx, col_name in enumerate(columns, start=1):
            cell = ws.cell(row=header_row, column=col_idx, value=col_name)
            cell.font = header_font
            cell.fill = header_fill
            cell.alignment = Alignment(horizontal='center', vertical='center')
            cell.border = border
        
        # 写入数据
        data_start_row = header_row + 1
        for row_idx, row_data in enumerate(rows, start=data_start_row):
            # row_data 是元组，需要按索引访问
            for col_idx in range(len(columns)):
                value = row_data[col_idx] if col_idx < len(row_data) else None
                cell = ws.cell(row=row_idx, column=col_idx + 1, value=value if value is not None else '')
                cell.font = normal_font
                cell.border = border
        
        # 调整列宽
        for col_idx in range(1, len(columns) + 1):
            col_letter = chr(64 + col_idx) if col_idx <= 26 else 'Z'
            ws.column_dimensions[col_letter].width = 20
    
    def _render_generic_data_quality_monitor(self, wb, data):
        """渲染通用数据同步质量报表到Excel"""
        from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
        
        ws = wb.active
        ws.title = "通用数据质量监控"
        
        # 标题样式
        title_font = Font(name='微软雅黑', size=16, bold=True)
        header_fill = PatternFill(start_color='409EFF', end_color='409EFF', fill_type='solid')
        header_font = Font(name='微软雅黑', size=11, bold=True, color='FFFFFF')
        normal_font = Font(name='微软雅黑', size=10)
        border = Border(
            left=Side(style='thin'),
            right=Side(style='thin'),
            top=Side(style='thin'),
            bottom=Side(style='thin')
        )
        
        descriptor = TemplateRegistry.get(self.template_code)
        report_title = self.title or (descriptor.name if descriptor else '通用数据同步质量报表')
        
        # 写入标题
        ws['A1'] = report_title
        ws['A1'].font = title_font
        
        # 确定表头
        headers = []
        header_key_map = {}
        if data.get('data') and len(data['data']) > 0:
            row = data['data'][0]
            # 按顺序添加字段
            if 'source_table' in row:
                headers.append('源表')
                header_key_map['源表'] = 'source_table'
            if 'target_table' in row:
                headers.append('目标表')
                header_key_map['目标表'] = 'target_table'
            if 'source_total_count' in row:
                headers.append('源表总数')
                header_key_map['源表总数'] = 'source_total_count'
            if 'target_total_count' in row:
                headers.append('目标表总数')
                header_key_map['目标表总数'] = 'target_total_count'
            if 'sync_rate' in row:
                headers.append('同步率')
                header_key_map['同步率'] = 'sync_rate'
            if 'data_status' in row:
                headers.append('数据状态')
                header_key_map['数据状态'] = 'data_status'
            # 添加其他字段
            for key in row:
                if key not in ['source_table', 'target_table', 'source_total_count', 'target_total_count', 'sync_rate', 'data_status']:
                    headers.append(key)
                    header_key_map[key] = key
        
        # 确定合并单元格的列范围
        last_col = chr(64 + len(headers)) if headers else 'I'
        ws.merge_cells(f'A1:{last_col}1')
        
        # 写入生成时间
        row_num = 2
        ws[f'A{row_num}'] = f"生成时间：{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
        ws[f'A{row_num}'].font = normal_font
        ws.merge_cells(f'A{row_num}:{last_col}{row_num}')
        
        # 写入统计时间范围
        row_num += 1
        if self.time_start and self.time_end:
            ws[f'A{row_num}'] = f"统计时间范围：{self.time_start} 至 {self.time_end}"
        elif self.time_start or self.time_end:
            time_range_str = f"统计时间：{self.time_start or ''} 至 {self.time_end or ''}"
            ws[f'A{row_num}'] = time_range_str
        else:
            ws[f'A{row_num}'] = "统计时间范围：全部数据"
        ws[f'A{row_num}'].font = normal_font
        ws.merge_cells(f'A{row_num}:{last_col}{row_num}')
        
        # 表头从下一行开始
        header_row = row_num + 1
        
        if headers:
            for col_idx, header in enumerate(headers, start=1):
                cell = ws.cell(row=header_row, column=col_idx, value=header)
                cell.font = header_font
                cell.fill = header_fill
                cell.alignment = Alignment(horizontal='center', vertical='center')
                cell.border = border
            
            # 写入数据
            data_start_row = header_row + 1
            for row_idx, row_data in enumerate(data.get('data', []), start=data_start_row):
                col_idx = 1
                for header in headers:
                    key = header_key_map.get(header, header)
                    value = row_data.get(key, '')
                    cell = ws.cell(row=row_idx, column=col_idx, value=value)
                    cell.font = normal_font
                    cell.border = border
                    col_idx += 1
            
            # 调整列宽
            for col_idx in range(1, len(headers) + 1):
                col_letter = chr(64 + col_idx) if col_idx <= 26 else 'Z'
                ws.column_dimensions[col_letter].width = 20
    
    def get_file_type(self) -> str:
        return 'excel'
    
    def _render_default(self, wb, data):
        """默认Excel渲染"""
        ws = wb.active
        ws.title = "报表数据"
        descriptor = TemplateRegistry.get(self.template_code)
        ws['A1'] = descriptor.name if descriptor else '数据报表'
        ws['A2'] = f"模板：{self.template_code}"


# 渲染器注册表
RENDERER_REGISTRY = {
    'html': HtmlRenderer,
    'excel': ExcelRenderer,
}


def get_renderer(file_type: str, template_code: str, title: str = None, time_start: str = None, time_end: str = None) -> BaseRenderer:
    """
    获取渲染器实例
    :param file_type: 文件类型（html/excel）
    :param template_code: 模板编码
    :param title: 报表标题（可选）
    :param time_start: 统计开始时间（可选）
    :param time_end: 统计结束时间（可选）
    :return: 渲染器实例
    """
    renderer_class = RENDERER_REGISTRY.get(file_type)
    if not renderer_class:
        raise ValueError(f"Unknown file type: {file_type}")
    
    return renderer_class(template_code, title=title, time_start=time_start, time_end=time_end)








